package com.rao.config.websecurity.permitcollect;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;


import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 收集放行的url
 */
@Slf4j
@Component
public class PermitAllCollectEventBean implements ApplicationListener<SecurityEvent> /*InitializingBean*/ {

    public final static List<String> permit_all_urls = new LinkedList<>();

    @Override
    public void onApplicationEvent(SecurityEvent event) {
        log.info("CollectEventBean监听到了ServletWebServerInitializedEvent---进行@PermitAnyOne的url收集-start");
        ConfigurableListableBeanFactory configurableListableBeanFactory = ConfigurableListableBeanFactoryUtil.configurableListableBeanFactory;
        for (String beanDefinitionName : configurableListableBeanFactory.getBeanDefinitionNames()) {
            BeanDefinition beanDefinition = configurableListableBeanFactory.getBeanDefinition(beanDefinitionName);
            //包扫描的bean
            if (beanDefinition instanceof ScannedGenericBeanDefinition) {
                ScannedGenericBeanDefinition scannedGenericBeanDefinition = (ScannedGenericBeanDefinition) beanDefinition;
                /** <?拿到该类带有@PermitAnyOne的所有的方法元数据【MethodMetadata】*/
                Set<MethodMetadata> methods = scannedGenericBeanDefinition.getMetadata().getAnnotatedMethods(PermitAnyOne.class.getName());
                if (methods.size() == 0) {
                    continue;
                }
                AnnotationMetadata metadata = ((ScannedGenericBeanDefinition) beanDefinition).getMetadata();
                Map<String, Object> classAnno = metadata.getAnnotationAttributes(RequestMapping.class.getName());
                //类上的url
                String classUrl = null;
                if (classAnno != null) {
                    Object path = classAnno.get("path");
                    if (path != null) {
                        String[] us = (String[]) path;
                        if (us.length >= 1) {
                            classUrl = us[0];
                        }
                    }
                }
                for (MethodMetadata methodMetadata : methods) {
                    try {
                        MultiValueMap<String, Object> attributes = methodMetadata.getAllAnnotationAttributes(RequestMapping.class.getName());
                        List<Object> pathObj = attributes.get("path");
                        if (pathObj != null && pathObj.size() >= 1) {
                            String[] os = (String[]) pathObj.get(0);
                            //方法上的url
                            String methodUrl = os[0];
                            String collectUrl = null;
                            if (classUrl != null) {
                                collectUrl = classUrl + methodUrl;
                            } else {
                                collectUrl = methodUrl;
                            }

                            permit_all_urls.add(collectUrl);
                            log.info("要permitAll的方法为-{}.{}", scannedGenericBeanDefinition.getBeanClassName(), methodMetadata.getMethodName());

                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        log.info("CollectEventBean监听到了ServletWebServerInitializedEvent---进行@PermitAnyOne的url收集-end");
    }
}
